package com.yfp.device.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.hy.corecode.idgen.WFGIdGenerator;
import com.yfp.common.core.utils.StringUtils;
import com.yfp.common.redis.service.RedisService;
import com.yfp.common.security.utils.SecurityUtils;
import com.yfp.device.domain.*;
import com.yfp.device.domain.dto.ComboMadeDoneDTO;
import com.yfp.device.domain.dto.OrderCreateDTO;
import com.yfp.device.domain.dto.QRCodeDTO;
import com.yfp.device.domain.vo.MakingPackageVO;
import com.yfp.device.enums.OrderStatus;
import com.yfp.device.enums.PackageStatus;
import com.yfp.device.mapper.ClientMapper;
import com.yfp.device.mapper.OrderListMapper;
import com.yfp.device.service.*;
import com.yfp.minapp.auth.api.RemoteClientService;
import com.yfp.operation.api.RemoteGroupService;
import com.yfp.operation.api.RemoteOperationService;
import com.yfp.operation.domain.RedisOrderDetail;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.yfp.common.core.constant.CacheConstants.MINAPP_ORDER_TAKE_QR_CODE_KEY;

/**
 * 
 * @version 1.0
 * @date 2024-06-18 17:08
 */
@Service
@Slf4j
public class MachineComboServiceImpl implements MachineComboService {

    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private OrderComboService orderComboService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private OrderMakeService orderMakeService;
    @Resource
    private WFGIdGenerator wfgIdGenerator;
    @Resource
    private RemoteOperationService remoteOperationService;
    @Resource
    private ClientMapper clientMapper;
    @Resource
    private OrderListMapper orderListMapper;
    @Resource
    private RedisService redisService;
    @Resource
    private DeviceCurrentComboStockService deviceCurrentComboStockService;
    @Resource
    private RemoteGroupService remoteGroupService;
    @Resource
    private RemoteClientService remoteClientService;
    @Resource
    private ClientHealthLogService clientHealthLogService;

    /**
     * 获取制作套餐信息，设备发起二维码取餐
     *
     * @param qrCodeId
     * @return
     */
    @Override
    @Transactional
    public R<MakingPackageVO> getMakingPackage(String qrCodeId) {
        // String makingPackage = redisTemplate.opsForValue().get(qrCodeId);
        Object makingPackageObj = redisService.getCacheObject(MINAPP_ORDER_TAKE_QR_CODE_KEY + qrCodeId);
        String makingPackage = JSONObject.toJSONString(makingPackageObj);

        log.info("qrCodeId：{} , makingPackage: {}", qrCodeId, makingPackage);
        if (Objects.isNull(makingPackageObj)) {
            return R.fail("二维码已过期");
        }
        QRCodeDTO qrCodeDTO = JSONObject.parseObject(makingPackage, QRCodeDTO.class);
        List<OrderDetail> details = qrCodeDTO.getDetailList();
        String orderId = qrCodeDTO.getOrderId();
        String operateType = qrCodeDTO.getOperateType();
//
//        JSONArray list = JSONObject.parse(makingPackage).getJSONArray("packageList");
//        String orderId = JSONObject.parse(makingPackage).getString("orderId");
//        String operateType = JSONObject.parse(makingPackage).getString("operateType");

        // 企业团餐业务判断
        List<OrderList> orderListsGroup = orderListMapper.getByOrderId(orderId);
        OrderList orderListsGroupFirst = CollUtil.getFirst(orderListsGroup);
        if (Objects.nonNull(orderListsGroupFirst) && StrUtil.equals("2", orderListsGroupFirst.getOrderType())) {

            // 团餐，判断是否在取餐时间范围内
            long expiredCount = orderListMapper.getByOrderId(orderId).stream().filter(item -> StrUtil.equals("2", item.getOrderType())).filter(item -> {
                log.info("企业团餐业务,校验取餐时间");
                DateTime useTime = DateUtil.offsetDay(item.getPayTime(), 1);
                DateTime nowDateTime = DateUtil.date();
                boolean in = DateUtil.isIn(useTime, DateUtil.beginOfDay(nowDateTime), DateUtil.endOfDay(nowDateTime));
                return !in;
            }).count();
            if (expiredCount > 0) {
                log.info("企业团餐业务,取餐时间已过：还未到取餐时间~");
                return R.fail("还未到取餐时间~");
            }

            // 判断设备是否有库存
            OrderCombo orderCombo = orderComboService.selectByid(orderId);
            List<OrderCreateDTO.ShopCart> collect = orderListsGroup.stream().collect(Collectors.groupingBy(item -> item.getComboId())).entrySet().stream().map(item -> {
                String key = item.getKey();
                List<OrderList> value = item.getValue();

                OrderCreateDTO.ShopCart shopCart = new OrderCreateDTO.ShopCart();
                shopCart.setComboId(key);
                shopCart.setCount(value.size());
                return shopCart;
            }).collect(Collectors.toList());
            // 校验库存
            log.info("企业团餐业务,校验库存，套餐信息：{}", orderListsGroup);
            Boolean isStockAvailable = deviceCurrentComboStockService.checkStockAvailability(collect, orderCombo.getMachineId());
            if (!isStockAvailable) {
                log.info("企业团餐业务,套餐库存不足：暂未补货，请晚点再来~");
                return R.fail("暂未补货，请晚点再来~");
            }
        }

        // 判断扫码设备与下单设备是否一致
        OrderCombo orderCombo = orderComboService.selectByid(orderId);
        log.info("套餐信息，orderCombo：{}", orderCombo);
        // 订单设备id
        String orderMachineId = orderCombo.getMachineId();
        // 获取设备id
        String machineId = SecurityUtils.getUsername();
        if (StringUtils.isEmpty(machineId)) {
            log.info("当前设备未登录");
            return R.fail("当前设备未登录");
        }

        if (!orderMachineId.equals(machineId)) {
            log.warn("反扫码设备与下单设备不一致,订单id:{},扫码设备id:{}", orderId, machineId);
            return R.fail("反扫码设备与下单设备不一致");
        }

//        if (!orderCombo.getStatus().equals(OrderStatus.AwaitPackage)) {
//            log.warn("设备反扫码获取套餐信息失败,原因反扫码订单已完成,订单id:{}", orderId);
//            return R.fail("当前订单已完成");
//        }
//
        // 制作对象
        List<OrderDetail> detailList = new ArrayList<>();
        List<String> orderDetailIds = details.stream().map(OrderDetail::getOrderDetailId).collect(Collectors.toList());
        List<OrderDetail> itemList = orderDetailService.findByDetailIds(orderDetailIds);
        for (OrderDetail orderDetail : itemList) {
            String status = orderDetail.getStatus();
            if (status.equals(PackageStatus.WaitingToBeMade.getStatus())) {
                detailList.add(orderDetail);
            }
        }
        // 判断制作对象是否有值
        if (detailList.isEmpty()) {
            return R.fail("当前订单无等待制作状态的套餐！");
        }


        Map<String, OrderMake> orderMakeMap = null;
        List<OrderMake> orderMakeList = orderMakeService.findByDetailIds(orderDetailIds);
        if (!orderMakeList.isEmpty()) {
            orderMakeMap = orderMakeList.stream().collect(Collectors.toMap(OrderMake::getOrderDetailId, Function.identity()));
        }

        Map<String, OrderDetail> orderDetailMap = itemList.stream().collect(Collectors.toMap(OrderDetail::getOrderDetailId, Function.identity()));

        Map<String, OrderDetail> detailMap = detailList.stream().collect(Collectors.toMap(OrderDetail::getOrderDetailId, Function.identity()));

        // 如果为制作二维码
        if (operateType.equals("Make")) {
            for (String detailId : orderDetailIds) {
                Long makeCount = 0L;
                if (!Objects.isNull(orderMakeMap) && orderMakeMap.get(detailId) != null) {
                    makeCount = orderMakeMap.get(detailId).getMakeCount();
                }
                Long count = detailMap.get(detailId).getCount();
                Long count1 = orderDetailMap.get(detailId).getCount();
                if ((makeCount + count) > count1) {
                    log.info("小程反扫码失败,原因需制作数量大于可制作数量,二维码反扫信息:{}", makingPackage);
                    return R.fail("小程反扫码失败,原因需制作数量大于可制作数量");
                }
            }
        }

        // 如果为取餐二维码
        if (operateType.equals("PickUp")) {
            for (OrderDetail orderDetail : itemList) {
                String status = orderDetail.getStatus();
                if (status.equals(PackageStatus.Refunded.getStatus())) {
                    return R.fail("订单已退款");
                }
                Long availableCount = orderDetail.getCompletedCount() - orderDetail.getPickedUpCount();
                Long count = detailMap.get(orderDetail.getOrderDetailId()).getCount();
                if (count > availableCount) {
                    log.info("小程序反扫码失败,原因需取餐数量大于制作完成数量,二维码反扫信息:{}", makingPackage);
                    return R.fail("小程序反扫码失败,原因需取餐数量大于制作完成数量");
                }
            }
        }

        MakingPackageVO makingPackageVO = new MakingPackageVO();
        // 获取客户信息
        String userId = orderCombo.getUserId();
        Client client = clientMapper.selectById(userId);
        String pickupNum = orderListsGroupFirst.getUserMobile().substring(7, 11);
        if (client != null) {
            // 头像
            makingPackageVO.setUserHeadUrl(client.getHeadImg());
            // 电话
            makingPackageVO.setPickupNum(pickupNum);
        }

        ArrayList<OrderDetail> ods = new ArrayList<>();
        ArrayList<RedisOrderDetail> rods = new ArrayList<>();
        Timestamp queueTime = new Timestamp(System.currentTimeMillis());
        Integer num = 1;
        for (OrderDetail orderDetail : detailList) {
            pickupNum = orderListsGroupFirst.getUserMobile().substring(7, 11);
            // 修改详情状态
            OrderDetail detail = new OrderDetail();
            detail.setOrderDetailId(orderDetail.getOrderDetailId());
            detail.setUpdateTime(new Timestamp(System.currentTimeMillis()));
            detail.setStatus(PackageStatus.WaitingToBeMade.getStatus());
            detail.setQueueTime(queueTime);
            detail.setScannedStatus(1);
            // 组装取餐码
            if (num < 10) {
                pickupNum = pickupNum + "-0" + num;
            } else {
                pickupNum = pickupNum + "-" + num;
            }
            log.info("订单号：{}，取餐码：{}", detail.getOrderId(), pickupNum);
            detail.setPickupNum(pickupNum);
            ods.add(detail);
            // 返回取餐码给设备
            orderDetail.setPickupNum(detail.getPickupNum());

            RedisOrderDetail addRedisOrderDetail = new RedisOrderDetail();
            addRedisOrderDetail.setDetailId(orderDetail.getOrderDetailId());
            addRedisOrderDetail.setQueueTime(queueTime);
            rods.add(addRedisOrderDetail);
            num = num + 1;
        }

        // 批量修改订单状态
        orderDetailService.updateDetails(ods);

        // 因为上面把异常订单筛掉了，  所以加个根据订单号赋值排队时间的方法
        orderDetailService.awaitQueueTime(orderId);

        List<OrderMake> makes = new ArrayList<>();
        List<String> detailIds = orderMakeList.stream().map(orderMake -> orderMake.getOrderDetailId()).collect(Collectors.toList());
        ArrayList<String> detailIdList = new ArrayList<>(CollectionUtils.removeAll(orderDetailIds, detailIds));
        if (CollUtil.isNotEmpty(detailIdList)) {
            for (String detailId : detailIdList) {
                OrderDetail orderDetail = detailMap.get(detailId);
                OrderMake orderMake = new OrderMake();
                orderMake.setOrderDetailId(orderDetail.getOrderDetailId());
                orderMake.setOrderMakeId(String.valueOf(wfgIdGenerator.next()));
                orderMake.setOrderId(orderId);
                orderMake.setMakeCount(orderDetail.getCount());
                orderMake.setCreateTime(new Timestamp(System.currentTimeMillis()));
                orderMake.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                makes.add(orderMake);
            }
            orderMakeService.insertAll(makes);
        }
        if (CollUtil.isNotEmpty(orderMakeList)) {
            ArrayList<OrderMake> orderMakes = new ArrayList<>();
            for (OrderMake orderMake : orderMakeList) {
                Long makeCount = orderMake.getMakeCount();
                OrderDetail orderDetail = detailMap.get(orderMake.getOrderDetailId());
                if (Objects.nonNull(orderDetail)) {
                    orderMake.setMakeCount(makeCount + orderDetail.getCount());
                }
                orderMake.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                orderMakes.add(orderMake);
            }
            orderMakeService.findUpdateMake(orderMakes);
        }


        LambdaQueryWrapper<OrderList> wrapper = new LambdaQueryWrapper<OrderList>().eq(OrderList::getOrderSn, orderId);
        List<OrderList> orderLists = orderListMapper.selectList(wrapper);
        redisTemplate.delete(MINAPP_ORDER_TAKE_QR_CODE_KEY + qrCodeId);

        // 缓存存储排队订单详情
//        List<RedisOrderDetail> redisOrderDetails = new ArrayList<>();
//        RedisOrderDetail addRedisOrderDetail=null;
//        for (OrderDetail orderDetail : detailList) {
//            addRedisOrderDetail = new RedisOrderDetail();
//            addRedisOrderDetail.setDetailId(orderDetail.getOrderDetailId());
//            addRedisOrderDetail.setQueueTime(queueTime);
//            redisOrderDetails.add(addRedisOrderDetail);
//        }
//        remoteOperationService.checkMachineMealMinAnomaly(redisOrderDetails);

        if (!orderLists.isEmpty()) {
            makingPackageVO.setPayTime(orderLists.get(0).getPayTime().getTime());
        }
        makingPackageVO.setOrderId(orderId);
        makingPackageVO.setPickupGoodsType("2FO");
        makingPackageVO.setPackageList(detailList);
        makingPackageVO.setOperateType(operateType);

        // 企业团餐业务判断
        if (Objects.nonNull(orderListsGroupFirst) && StrUtil.equals("2", orderListsGroupFirst.getOrderType())) {
            // 减少设备库存
            OrderCombo orderComboGroup = orderComboService.selectByid(orderId);
            List<OrderCreateDTO.ShopCart> collect = orderListsGroup.stream().collect(Collectors.groupingBy(item -> item.getComboId())).entrySet().stream().map(item -> {
                String key = item.getKey();
                List<OrderList> value = item.getValue();

                OrderCreateDTO.ShopCart shopCart = new OrderCreateDTO.ShopCart();
                shopCart.setComboId(key);
                shopCart.setCount(value.size());
                return shopCart;
            }).collect(Collectors.toList());
            deviceCurrentComboStockService.decreaseStockQuantity(collect, orderComboGroup.getMachineId());
        }

        return R.ok(makingPackageVO);
    }


    /**
     * 设备上报套餐制作完成，设备上报二维码取餐完成
     *
     * @param comboMadeDoneDTO
     * @return
     */
    @Override
    @Transactional
    public R<String> reportPackageMadeDone(ComboMadeDoneDTO comboMadeDoneDTO) {
        String orderDetailId = comboMadeDoneDTO.getOrderDetailId();
        DateTime date = DateUtil.date();
        OrderDetail orderDetail = orderDetailService.getById(orderDetailId);
        if (orderDetail == null) {
            return R.fail("该套餐详情不存在");
        }

        log.info("订单详情信息:{},状态:{}", orderDetail, comboMadeDoneDTO.getStatus());

        String orderId = orderDetail.getOrderId();
        LambdaUpdateWrapper<OrderDetail> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(OrderDetail::getOrderDetailId, orderDetailId);
        updateWrapper.set(OrderDetail::getUpdateTime, date);
        // 制作完成状态   更新制作数量和状态
        if (comboMadeDoneDTO.getStatus().equals(PackageStatus.MadeDone.getStatus())) {
            long completedCount = orderDetail.getCompletedCount() + 1;
            // 套餐已制作数量与套餐数量比较
            if (completedCount > orderDetail.getCount()) {
                completedCount = orderDetail.getCount();
            }
            // 验证套餐制作完成数量，确定是否修改套餐状态
            if (completedCount == orderDetail.getCount()) {
                updateWrapper.set(OrderDetail::getStatus, PackageStatus.MadeDone.getStatus());
            }
            updateWrapper.set(OrderDetail::getCompletedCount, completedCount);
            orderDetailService.update(updateWrapper);

            // 查询订单号关联的所有订单信息
            List<OrderDetail> orderDetails = orderDetailService.getByOrderId(orderId);
            for (OrderDetail detail : orderDetails) {
                if (detail.getOrderDetailId().equals(orderDetailId)) {
                    detail.setCompletedCount(completedCount);
                }
            }
            log.info("订单详情列表:{}", orderDetails);
            boolean allMatch = orderDetails.stream().allMatch(item -> NumberUtil.equals(item.getCompletedCount(), 1L));
            log.info("订单详情列表是否全部制作完成:{}", allMatch);
            if (allMatch) {
                remoteClientService.notifyTakeFood(orderDetail.getOrderId(), comboMadeDoneDTO.getOrderDetailId(), date);
            }
            return R.ok();
        }

        // 取餐完成状态     更新取走数量和状态
        if (comboMadeDoneDTO.getStatus().equals(PackageStatus.PickupIsComplete.getStatus())) {
            long pickedUpCount = orderDetail.getPickedUpCount() + 1;
            if (pickedUpCount > orderDetail.getCount()) {
                pickedUpCount = orderDetail.getCount();
            }

            // 验证套餐取餐数量，确定是否修改套餐状态
            if (pickedUpCount == orderDetail.getCount()) {
                updateWrapper.set(OrderDetail::getStatus, PackageStatus.PickupIsComplete.getStatus());
            }
            updateWrapper.set(OrderDetail::getPickedUpCount, pickedUpCount);
            orderDetailService.update(updateWrapper);
            // orderList状态改成已完成
            LambdaUpdateWrapper<OrderList> wrapper = new LambdaUpdateWrapper<OrderList>().set(OrderList::getPayStatus, 3).eq(OrderList::getId, orderDetailId);
            orderListMapper.update(null, wrapper);

            // 订单完成保存客户健康餐饮记录
            clientHealthLogService.orderFinishSave(orderDetailId);

            // 如果已全部取走
            if (pickedUpCount == orderDetail.getCount()) {
                // 查询订单号关联的所有订单信息
                List<OrderDetail> orderDetails = orderDetailService.getByOrderId(orderId);
                // 循环校验判断是否所有订单都取完
                for (OrderDetail item : orderDetails) {
                    if (!item.getStatus().equals(PackageStatus.PickupIsComplete.getStatus())) {
                        return R.ok();
                    }
                }
                // 如果都取完则更新订单相关联的表
                OrderCombo orderCombo = new OrderCombo();
                orderCombo.setOrderId(orderId);
                orderCombo.setStatus(OrderStatus.Finish.getStatus());
                orderCombo.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                orderComboService.updateOrderStatus(orderCombo);
                LambdaQueryWrapper<OrderMake> makeLambdaQueryWrapper = new LambdaQueryWrapper<OrderMake>().eq(OrderMake::getOrderId, orderId);
                orderMakeService.remove(makeLambdaQueryWrapper);
//                updateWrapper.set(OrderDetail::getQueueTime, null);
                orderDetailService.update(updateWrapper);
//                LambdaUpdateWrapper<OrderList> wrapper1 = new LambdaUpdateWrapper<OrderList>().set(OrderList::getPayStatus, 3).eq(OrderList::getOrderSn, orderId);
//                orderListMapper.update(null, wrapper1);
                OrderCombo orderCombo1 = orderComboService.selectByid(orderId);
                // 邀请有礼活动-发放被邀请人优惠券
                log.info("订单号:{},邀请有礼活动-发放邀请人优惠券", orderId);
                remoteOperationService.issueInviteCouponForHost(orderCombo1.getUserId());

                // 将客户的点位标签更新为当前订单的点位
                remoteOperationService.updatePositionId(orderCombo1.getOrderId());

                OrderCombo ocd = orderComboService.getById(orderId);
                if (ocd.getEnterpriseOrderSn() != null) {
                    remoteGroupService.updateFinishTime(ocd.getEnterpriseOrderSn());
                }
                remoteOperationService.lotteryCount(ocd.getUserId(), ocd.getPrice(), ocd.getCityName());
                remoteOperationService.activitySignInsCount(ocd.getUserId(), ocd.getCityName());
                remoteOperationService.giveIntegral(ocd.getOrderId());
            }
            return R.ok();
        }

        // 制作异常
        if (comboMadeDoneDTO.getStatus().equals(PackageStatus.MakeExceptions.getStatus())) {
            log.info("设备上报状态,进入MakeExceptions,orderDetailId:{},status:{},", comboMadeDoneDTO.getOrderDetailId(), comboMadeDoneDTO.getStatus());
            updateWrapper.set(OrderDetail::getStatus, PackageStatus.MakeExceptions.getStatus());
//            updateWrapper.set(OrderDetail::getQueueTime, null);
            orderDetailService.update(updateWrapper);
            return R.ok();
        }

        // 正在制作
        if (comboMadeDoneDTO.getStatus().equals(PackageStatus.InTheMaking.getStatus())) {
            log.info("设备上报状态,进入InTheMaking,orderDetailId:{},status:{},", comboMadeDoneDTO.getOrderDetailId(), comboMadeDoneDTO.getStatus());
            updateWrapper.set(OrderDetail::getStatus, PackageStatus.InTheMaking.getStatus());
            orderDetailService.update(updateWrapper);
            return R.ok();
        }

        // 等待制作
        if (comboMadeDoneDTO.getStatus().equals(PackageStatus.WaitingToBeMade.getStatus())) {
            log.info("设备上报状态,进入WaitingToBeMade,orderId:{},orderDetailIds:{},", comboMadeDoneDTO.getOrderId(), comboMadeDoneDTO.getOrderDetailIds());
            OrderCombo orderCombo = orderComboService.getById(comboMadeDoneDTO.getOrderId());
            if (orderCombo == null) {
                return R.fail("订单不存在");
            }
            // 判断订单状态
            if (!orderCombo.getStatus().equals(OrderStatus.AwaitPackage.getStatus())) {
                log.info("订单状态不支持制作");
                return R.fail("该订单状态不支持该操作");
            }
            // 设置状态
            List<OrderDetail> orderDetails = new ArrayList<>();
            for (String detailId : comboMadeDoneDTO.getOrderDetailIds()) {
                orderDetail = new OrderDetail();
                orderDetail.setOrderDetailId(detailId);
                orderDetail.setStatus(PackageStatus.WaitingToBeMade.getStatus());
                orderDetails.add(orderDetail);
            }

            // 批量修改状态
            orderDetailService.updateOrderDetail(orderDetails);
        }

        return null;
    }
}
